package com.zm.campus.service.impl;



import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zm.campus.dao.*;
import com.zm.campus.pojo.*;
import com.zm.campus.query.TreeHoleQuery;
import com.zm.campus.service.ITreeHoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zm.campus.util.AssertUtil;
import com.zm.campus.util.GetHeadersInfo;
import com.zm.campus.vo.AuditListVo;
import com.zm.campus.vo.AuditTreeHoleVo;
import com.zm.campus.vo.LoginReturnVo;
import com.zm.campus.vo.TreeHoleNewComent;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import sun.reflect.generics.tree.Tree;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zm
 */
@Service
public class TreeHoleServiceImpl extends ServiceImpl<TreeHoleMapper, TreeHole> implements ITreeHoleService {

    @Autowired
    private TreeHoleMapper treeHoleMapper;
    @Autowired
    private CommPointThMapper commPointThMapper;
    @Autowired
    private AuditTreeHoleMapper auditTreeHoleMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private TreeAvatarMapper  treeAvatarMapper;
    @Autowired
    private UserServiceImpl userService;

    //通过分页获取所有树洞的列表信息
    @Override
    public RespBean getAllTreeHole(TreeHoleQuery treeHoleQuery) {//通过树洞的内容和用户当前所在学校的id去查
        User user = userMapper.selectById(treeHoleQuery.getUserId());
        AssertUtil.isTrue(user==null,RespBeanEnum.UserError);
        treeHoleQuery.setSchoolId(user.getSchoolId());
        Map<String,Object> map=new HashMap<>();
        //开启分页
        PageHelper.startPage(treeHoleQuery.getPage(),treeHoleQuery.getLimit());
        //得到对应的分页对象
        PageInfo<TreeHole> planPageInfo=new PageInfo<>(treeHoleMapper.getAllTreeHole(treeHoleQuery));
        //判断树洞表中是否当前用户有评论或点赞过，点赞的状态是怎样的
        for (TreeHole th:planPageInfo.getList()){
            if (StringUtils.isNotBlank(th.getPointUidList())&&th.getPointUidList().contains(treeHoleQuery.getUserId())){//说明当前用户有评论过这条树洞
                th.setNowUserIsPoint(true);
            }else {
                th.setNowUserIsPoint(false);
            }
            if (StringUtils.isNotBlank(th.getPointUidList())){
                String substring = th.getPointUidList().substring(1, th.getPointUidList().length() - 1);
                if(substring.length()==0){
                    th.setGoodsPoint(0L);
                }else {
                    String[] split = substring.split(",");
                    th.setGoodsPoint(Long.valueOf(split.length));
                }
            }
        }
        //设置map对象
        map.put("count",planPageInfo.getTotal());
        //设置好分页的列表
        map.put("data",planPageInfo.getList());
        return RespBean.success(map);
    }



    //评论树洞/
    @Transactional
       @Override
    public RespBean commentsTreeHole(CommPointTh commPointTh) throws IOException {
            //参数校验
            AssertUtil.isTrue(commPointTh.getThId()==null||StringUtils.isBlank(commPointTh.getCommentUserId()),
                    RespBeanEnum.BIND_ERROR);//待更新的树洞或评论人的用户学号不能为空
            AssertUtil.isTrue(StringUtils.isBlank(commPointTh.getComment()),RespBeanEnum.CommentNotNull);
            User commentor = userMapper.selectById(commPointTh.getCommentUserId());//评论者个人信息
        //通过树洞id查看当前这条树洞的comm_uid_list
            TreeHole treeHole = treeHoleMapper.selectById(commPointTh.getThId());
            AssertUtil.isTrue(treeHole==null,RespBeanEnum.TreeHoleNoTExist);
            //设置评论时间，并执行更新操作
            commPointTh.setCommDate(new Date());
            commPointTh.setDepartment(commentor.getDepartment());
            //执行跟新树洞（添加当前评论者的id）
            AssertUtil.isTrue(commPointThMapper.insert(commPointTh)!=1,RespBeanEnum.UpdateError);
            //给发布者发送一个新评论提醒
            WebSocketServer.sendInfo("树洞新评论",treeHole.getReleaseUserId());

            return RespBean.success();
    }

    //树洞点赞、取消点赞
    @Transactional
    @Override
    public RespBean addOrCancelGPoint(Long thId,Boolean isPoint, String pointUserId) {//接收的是树洞的id、是否点赞、当前用户的id
        TreeHole treeHole = treeHoleMapper.selectById(thId);//先判断这条树洞存不存在
        AssertUtil.isTrue(treeHole==null,RespBeanEnum.TreeHoleNoTExist);
        AssertUtil.isTrue(userMapper.selectById(pointUserId)==null,RespBeanEnum.ReleaseUserNull);//点赞的用户不存在
        //更新树洞表中的评论用户id列表的值
        if (isPoint){//点赞的逻辑处理
            AssertUtil.isTrue(StringUtils.isNotBlank(treeHole.getPointUidList())
                    &&treeHole.getPointUidList().contains(pointUserId),RespBeanEnum.UserIsPoint);//说明当前用户已点赞
            //准备一个list集合
            List<String> pointUidList =Collections.synchronizedList(new ArrayList<>());//线程安全
            //判断这条树洞的point_uid_list里是否有值//新加的评论用户id
            if(StringUtils.isNotBlank(treeHole.getPointUidList())){//该树洞无人点赞的情况下则加当前的用户id
                //把当前用户id存到树洞表评论的用户list集合中，代表当前用户已评论或点赞过这条树洞
                if (StringUtils.isNotBlank(treeHole.getPointUidList().substring(1,treeHole.getPointUidList().length()-1).replace(" ",""))){
                    pointUidList.add(treeHole.getPointUidList().substring(1,treeHole.getPointUidList().length()-1).replace(" ",""));
                }
            }
            pointUidList.add(pointUserId);
            treeHole.setPointUidList(pointUidList.toString());
        }else {//取消点赞的逻辑处理
            AssertUtil.isTrue( StringUtils.isBlank(treeHole.getPointUidList()),RespBeanEnum.SystemBusy);//没人点赞还要取消点赞则返回繁忙
            AssertUtil.isTrue(!treeHole.getPointUidList().contains(pointUserId),RespBeanEnum.UserNotPoint);//判断当前用户有没有包含在里面
            //到这里说明树洞的点赞列表里面有包含当前要取消点赞的用户//里面的数据转为list
            String substring=treeHole.getPointUidList().substring(1,treeHole.getPointUidList().length()-1).replace(" ","");
            String[] split = substring.split(",");//这是切割后的形成的字符串数组//原本的评论用户id
            List arrList =  new ArrayList(Arrays.asList(split));
            arrList.remove(pointUserId);//移除掉取消点赞的用户
            treeHole.setPointUidList(arrList.toString());
        }
        //更新树洞表的评论用户id集合，并且更新总的点赞数
        AssertUtil.isTrue(treeHoleMapper.updateById(treeHole)<1,RespBeanEnum.UpdateError);
        return RespBean.success();
    }

    @Transactional
    //提交树洞审核
    @Override
    public RespBean submitTreeHole(AuditTreeHoleVo auditTreeHoleVo) {
        String content = auditTreeHoleVo.getContent();
        String title= auditTreeHoleVo.getTitle().trim();
        AuditTreeHole auditingTH = auditTreeHoleMapper.selectOne(new QueryWrapper<AuditTreeHole>().eq("release_user_id", auditTreeHoleVo.getReleaseUserId())
                .eq("audit_status", 0));
        AssertUtil.isTrue(auditingTH!=null,RespBeanEnum.AuditIsDoing);//当前用户已有发表树洞待审核，等管理员审核完成后才可以继续提交树洞
        User user = userMapper.selectById(auditTreeHoleVo.getReleaseUserId());
        AssertUtil.isTrue(user==null,RespBeanEnum.ReleaseUserNull);
        //参数校验
        AssertUtil.isTrue(StringUtils.isBlank(auditTreeHoleVo.getReleaseUserId()),RespBeanEnum.ReleaseUidNotNull);
        AssertUtil.isTrue(StringUtils.isBlank(title)|| title.length()>20||title.length()<1,RespBeanEnum.ReleaseTitleError);
        AssertUtil.isTrue(StringUtils.isBlank(content),RespBeanEnum.ReleaseContentError);

        //校验完成，设置默认值。判断受影响行数
        AuditTreeHole auditTreeHole=new AuditTreeHole();
        auditTreeHole.setReleaseUserId(auditTreeHoleVo.getReleaseUserId());
        auditTreeHole.setContent(content);
        auditTreeHole.setReleaseUserName(user.getUserName());
        auditTreeHole.setTitle(title);
        auditTreeHole.setReleaseDate(new Date());
        auditTreeHole.setSchoolId(user.getSchoolId());
        auditTreeHole.setAuditStatus(0);//审核状态，0待审核，1通过，2未通过

        AssertUtil.isTrue(auditTreeHoleMapper.insert(auditTreeHole)!=1,RespBeanEnum.SystemBusy);
        return RespBean.success();
    }

    //管理员审核树洞
    @Transactional
    @Override
    public RespBean registerTreeHole(AuditListVo auditListVo,Boolean isAudit,String role) {
        AssertUtil.isTrue(!role.equals("admin"),RespBeanEnum.InsufficientAuthority);
        //通过待审核的id查询审核树洞表
        AssertUtil.isTrue(auditListVo.getCheckedAuditList().isEmpty()||isAudit==null,RespBeanEnum.AuditListIsNull);
        auditListVo.getCheckedAuditList().forEach(auditTreeHoleId -> {//遍历查询集合里面的所有待审核的树洞
            AuditTreeHole auditTreeHole = auditTreeHoleMapper.selectById(auditTreeHoleId);
            User user = userMapper.selectById(auditTreeHole.getReleaseUserId());
            AssertUtil.isTrue(user==null,RespBeanEnum.ReleaseUserIsNotExist);
            AssertUtil.isTrue(auditTreeHole==null,RespBeanEnum.AuditTreeHoleNotExist);
            AssertUtil.isTrue(auditTreeHole.getAuditStatus()!=0,RespBeanEnum.THIsAudited);
            if (isAudit){//说明审核通过
                auditTreeHole.setAuditStatus(1);//审核表的
                //树洞表的
                TreeHole treeHole = new TreeHole();
                treeHole.setReleaseSchoolId(user.getSchoolId());
                treeHole.setGoodsPoint(0L);
                treeHole.setContent(auditTreeHole.getContent());
                treeHole.setReleaseDate(auditTreeHole.getReleaseDate());
                treeHole.setReleaseUserId(auditTreeHole.getReleaseUserId());
                treeHole.setTitle(auditTreeHole.getTitle());
                AssertUtil.isTrue(treeHoleMapper.insert(treeHole)!=1,RespBeanEnum.SystemBusy);
            }else {
                auditTreeHole.setAuditStatus(2);
            }
            auditTreeHole.setAuditDate(new Date());//设置审核时间
            AssertUtil.isTrue(auditTreeHoleMapper.updateById(auditTreeHole)!=1,RespBeanEnum.SystemBusy);
        });

        return RespBean.success();
    }

    //删除指定id的树洞
    @Transactional
    @Override
    public RespBean deleteTreeHoleById(Long thId,String role) {
        AssertUtil.isTrue(!role.equals("admin"),RespBeanEnum.InsufficientAuthority);//权限不足
        AssertUtil.isTrue(treeHoleMapper.selectById(thId)==null,RespBeanEnum.TreeHoleNoTExist);//当前树洞不存在
        if (commPointThMapper.selectByThId(thId)>0){//说明有人评论过或者点赞过，这个评论表才有对应的数据，才能删除
            AssertUtil.isTrue(commPointThMapper.deleteByThId(thId)<1,RespBeanEnum.SystemBusy);
        }

        AssertUtil.isTrue(treeHoleMapper.deleteById(thId)!=1,RespBeanEnum.SystemBusy);

        return RespBean.success();
    }

    //获取当前需要审核的树洞的数量
    @Override
    public RespBean getNewAudit(String userId) {
        User user = userMapper.selectById(userId);
        if (user.getRole().equals("ordinary")){
            return RespBean.success(null);
        }
        Integer num= auditTreeHoleMapper.getNewAudit(user.getSchoolId());
        return RespBean.success(num);
    }

    //管理员获取所有待审核的树洞
    @Override
    public RespBean getAllAudit(LoginReturnVo loginReturnVo,HttpServletRequest request) {
        isLogin(loginReturnVo);//判断当前用户是否登录
        User user = userMapper.selectById(loginReturnVo.getUserId());
        AssertUtil.isTrue(user==null,RespBeanEnum.ReleaseUserNull);
        //判断是否有查询的权限
        AssertUtil.isTrue(!loginReturnVo.getRole().equals("admin"),RespBeanEnum.InsufficientAuthority);//权限不足

        List<AuditTreeHole> auditTreeHoleList= auditTreeHoleMapper.getAllAuditTreeHole(user.getSchoolId());
        return RespBean.success(auditTreeHoleList);
    }

    //管理员修改树洞头像
    @Override
    public RespBean updateTreeAvatar(MultipartFile treeAvatarFile, String userId,HttpServletRequest request) throws IOException {
        User user = userMapper.selectById(userId);
        AssertUtil.isTrue(user==null,RespBeanEnum.ReleaseUserNull);
        AssertUtil.isTrue(!user.getRole().equals("admin"),RespBeanEnum.InsufficientAuthority);//权限不足
        TreeAvatar treeAvatar = treeAvatarMapper.selectById(user.getSchoolId());
        AssertUtil.isTrue(treeAvatar.getTreeAvatar().equals(treeAvatarFile.getOriginalFilename()),RespBeanEnum.AvatarIsExist);
        //检查图片格式
        userService.checkImageType(treeAvatarFile);
        treeAvatar.setLastUpdateAdminId(userId);
        treeAvatar.setTreeAvatar(treeAvatarFile.getOriginalFilename());
        treeAvatar.setUpdateAvatarTime(new Date());
        AssertUtil.isTrue(treeAvatarMapper.updateById(treeAvatar)!=1,RespBeanEnum.SystemBusy);
        return RespBean.success(treeAvatarFile.getOriginalFilename());
    }

    //获取当前登录用户所在学校的树洞的图片
    @Override
    public RespBean getTreeAvatar(String userId) {
        User user = userMapper.selectById(userId);
        AssertUtil.isTrue(user==null,RespBeanEnum.ReleaseUserNull);
        TreeAvatar treeAvatar = treeAvatarMapper.selectById(user.getSchoolId());
        if (treeAvatar!=null){
            AssertUtil.isTrue(StringUtils.isEmpty(treeAvatar.getTreeAvatar()) ,RespBeanEnum.SystemBusy);
        }
        return RespBean.success(treeAvatar);
    }

    //获取指定用户的树洞新评论消息
    @Override
    public RespBean getNewCommentByUid(String userId) {
        List<TreeHoleNewComent> newComentList = treeHoleMapper.queryTHByUid(userId);
        for (TreeHoleNewComent treeHole : newComentList) {
            //树洞评论的子表
            List<CommPointTh> commPointThList = commPointThMapper.queryAllCommentByTHId(treeHole.getId());
            treeHole.setCommPointThs(commPointThList);
            //该树洞的点赞总数
            if (StringUtils.isBlank(treeHole.getPointUidList())){
                treeHole.setGoodsPoint(0L);
            }else {
                String substring = treeHole.getPointUidList().substring(1, treeHole.getPointUidList().length() - 1).replace(" ","");
                if(substring.length()==0){
                    treeHole.setGoodsPoint(0L);
                }else {
                    String[] split = substring.split(",");
                    treeHole.setGoodsPoint(Long.valueOf(split.length));
                }
            }
        }
        return RespBean.success(newComentList);
    }


    //判断当前用户是否登录
    private void  isLogin(LoginReturnVo loginReturnVo){
        String userId = loginReturnVo.getUserId();
        String role = loginReturnVo.getRole();
        String token = loginReturnVo.getToken();
        AssertUtil.isTrue(StringUtils.isBlank(userId)||StringUtils.isBlank(role)||StringUtils.isBlank(token)
                ,RespBeanEnum.UserError);
        //获取服务器缓存中的登录用户的数据。并比较
        LoginReturnVo  redisIdentityVo = (LoginReturnVo)redisTemplate.opsForValue().get("user:"+token);
        AssertUtil.isTrue(!token.equals(redisIdentityVo.getToken()),
                RespBeanEnum.UserNotLogin);//说明当前用户未登录
    }

}
